﻿using Serilog;
using Serilog.Events;
using Serilog.Filters;

namespace Net8.Project.Common.LogHelper
{
    /// <summary>
    /// Serilog LoggerConfiguration 扩展方法
    /// </summary>
    public static class LoggerConfigurationExtensions
    {
        /// <summary>
        /// 配置日志输出到控制台，区分普通日志和 SQL 日志
        /// </summary>
        /// <param name="loggerConfiguration">LoggerConfiguration 实例</param>
        /// <returns>LoggerConfiguration 实例</returns>
        public static LoggerConfiguration WriteToConsole(this LoggerConfiguration loggerConfiguration)
        {
            // 输出普通日志
            loggerConfiguration = loggerConfiguration.WriteTo.Logger(lg =>
                lg.Filter.ByIncludingOnly(
                        WithPropertyExt<string>(LogContextExtension.LogSource, s => !LogContextExtension.AopSql.Equals(s)))
                  .WriteTo.Console());

            // 输出 SQL 日志
            //loggerConfiguration = loggerConfiguration.WriteTo.Logger(lg =>
            //    lg.Filter.ByIncludingOnly(
            //            Matching.WithProperty<string>(LogContextExtension.LogSource, s => LogContextExtension.AopSql.Equals(s)))
            //      .WriteTo.Console());

            return loggerConfiguration;
        }

        /// <summary>
        /// 配置日志输出到文件，区分普通日志和 SQL 日志
        /// </summary>
        /// <param name="loggerConfiguration">LoggerConfiguration 实例</param>
        /// <returns>LoggerConfiguration 实例</returns>
        public static LoggerConfiguration WriteToFile(this LoggerConfiguration loggerConfiguration)
        {
            // 输出普通日志
            loggerConfiguration = loggerConfiguration.WriteTo.Logger(lg =>
                lg.Filter.ByIncludingOnly(
                        WithPropertyExt<string>(LogContextExtension.LogSource, s => !LogContextExtension.AopSql.Equals(s)))
                  .WriteTo.Async(s => s.File(
                        Path.Combine("Logs", "Log.txt"),
                        rollingInterval: RollingInterval.Day,
                        outputTemplate: LogContextExtension.FileMessageTemplate,
                        retainedFileCountLimit: 31)));

            // 输出 SQL 日志
            loggerConfiguration = loggerConfiguration.WriteTo.Logger(lg =>
                lg.Filter.ByIncludingOnly(
                        Matching.WithProperty<string>(LogContextExtension.LogSource, s => LogContextExtension.AopSql.Equals(s)))
                  .WriteTo.Async(s => s.File(
                        Path.Combine("Logs", LogContextExtension.AopSql, "AopSql.txt"),
                        rollingInterval: RollingInterval.Day,
                        outputTemplate: LogContextExtension.FileMessageTemplate,
                        retainedFileCountLimit: 31)));

            return loggerConfiguration;
        }

        /// <summary>
        /// 自定义属性过滤器，支持泛型类型和值判断
        /// </summary>
        /// <typeparam name="T">属性值类型</typeparam>
        /// <param name="propertyName">属性名</param>
        /// <param name="predicate">属性值判断条件</param>
        /// <returns>日志事件过滤委托</returns>
        public static Func<LogEvent, bool> WithPropertyExt<T>(string propertyName, Func<T, bool> predicate)
        {
            // 如果不包含属性，认为通过（true）
            return e =>
            {
                if (!e.Properties.TryGetValue(propertyName, out var propertyValue))
                    return true;

                return propertyValue is ScalarValue { Value: T value } && predicate(value);
            };
        }
    }
}
